/*
    抽象层：通信所用元素的抽象
*/

#pragma once

#include "fields.hpp"
#include <memory>
#include <functional>

namespace myrpc
{
    //消息
    class BaseMessage
    {
    public:
        typedef std::shared_ptr<BaseMessage> ptr;
        virtual ~BaseMessage(){};

        virtual std::string rid() {return _rid;}
        virtual void setId(const std::string& rid) {_rid = rid;}

        virtual MType mtype() {return _mtype;}
        virtual void setMType(MType mtype) {_mtype = mtype;}

        virtual std::string serialize() = 0;
        virtual void unserialize(const std::string&) = 0;
        virtual bool check() = 0;
    private:
        MType _mtype; // 消息类型
        std::string _rid; // 消息id
    };

    //缓冲区
    class BaseBuffer 
    {
    public:
        typedef std::shared_ptr<BaseBuffer> ptr;
        virtual size_t readableSize() = 0;
        virtual int32_t peekInt32() = 0;
        virtual void retrieveInt32() = 0;
        virtual int32_t readInt32() = 0;
        virtual std::string retrieveAsString(size_t len) = 0;
    };

    //协议
    class BaseProtocol 
    {
    public:
        typedef std::shared_ptr<BaseProtocol> ptr;
        virtual bool canProcessed(const BaseBuffer::ptr &buf) = 0;
        virtual bool onMessage(const BaseBuffer::ptr &buf, BaseMessage::ptr &msg) = 0;
        virtual std::string serialize(const BaseMessage::ptr &msg) = 0;
    };

    //连接
    class BaseConnection 
    {
    public:
        typedef std::shared_ptr<BaseConnection> ptr;
        virtual void send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
    private:
        BaseProtocol::ptr _protocol;
    };

    using ConnectionCallback = std::function<void(const BaseConnection::ptr&)>;
    using CloseCallback = std::function<void(const BaseConnection::ptr&)>;
    using MessageCallback = std::function<void(const BaseConnection::ptr&, BaseMessage::ptr&)>;

    //服务端
    class BaseServer 
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        virtual void setConnectionCallback(const ConnectionCallback& cb) {_cb_connection = cb;}
        virtual void setCloseCallback(const CloseCallback& cb) {_cb_close = cb;}
        virtual void setMessageCallback(const MessageCallback& cb) {_cb_message = cb;}
        virtual void start() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };

    //客户端
    class BaseClient 
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        virtual void setConnectionCallback(const ConnectionCallback& cb) {_cb_connection = cb;}
        virtual void setCloseCallback(const CloseCallback& cb) {_cb_close = cb;}
        virtual void setMessageCallback(const MessageCallback& cb) {_cb_message = cb;}
        virtual void connect() = 0;
        virtual void shutdown() = 0;
        virtual bool send(const BaseMessage::ptr&) = 0;
        virtual BaseConnection::ptr connection() = 0;
        virtual bool connected() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };
}